package tpase.client.Handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import it.unisa.dia.gas.jpbc.Element;
import it.unisa.dia.gas.jpbc.Pairing;
import tpase.client.VO.Address;
import tpase.client.VO.Message;
import tpase.client.VO.StatusCode;
import tpase.client.VO.VerifyInfo;
import tpase.util.Util;

import java.util.List;
import java.util.Map;

public class ClientKGHandler extends ChannelInboundHandlerAdapter {
    private Pairing pairing;
    private String uid;
    private Element x_pwd;
    private Element com_m;
    private List<byte[]> idList;
    private List<Element> y1iList;
    private List<byte[]> c_Y2iList;
    private List<VerifyInfo> verifyList;
    private final Object lock;
    private int t;
    private List<Element> xServerList;

    public ClientKGHandler(Pairing pairing, String uid, Element xPwd, Element com_m, List<byte[]> idList, List<Element> y1iList, List<byte[]> c_Y2iList,  List<VerifyInfo> verifyList, Object lock, int t, List<Element> xServerList) {
        this.pairing = pairing;
        this.uid = uid;
        this.x_pwd = xPwd;
        this.com_m = com_m;
        this.idList = idList;
        this.y1iList = y1iList;
        this.c_Y2iList = c_Y2iList;
        this.verifyList = verifyList;
        this.lock = lock;
        this.t = t;
        this.xServerList = xServerList;
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Message request = new Message(StatusCode.KG_REQUEST);
        Map<String, byte[]> map = request.getMap();
        map.put("uid", uid.getBytes());
        map.put("x_pwd", x_pwd.toBytes());
        map.put("com_m", com_m.toBytes());
        map.put("idList", Util.toJson(idList).getBytes());

        ctx.writeAndFlush(request);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Message respond = (Message) msg;
        int statusCode = respond.getStatusCode();
        if (statusCode == StatusCode.KG_RESPONSE) {
            KGResponse(ctx, respond);
            ctx.close();
        }
    }

    private void KGResponse(ChannelHandlerContext ctx, Message respond) {
        Map<String, byte[]> map = respond.getMap();
        Element Y_1i = pairing.getGT().newElementFromBytes(map.get("Y_1i"));
        byte[] c_Y2i = map.get("c_Y2i");
        Element ci = pairing.getZr().newElementFromBytes(map.get("ci"));
        Element ui = pairing.getZr().newElementFromBytes(map.get("ui"));
        Element x = pairing.getZr().newElementFromBytes(map.get("x"));

        synchronized (lock) {
            y1iList.add(Y_1i);
            c_Y2iList.add(c_Y2i);
            VerifyInfo verifyInfo = new VerifyInfo(ui, Y_1i, ci, x);
            verifyList.add(verifyInfo);
            xServerList.add(x);
            lock.notifyAll();
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("ClientKGHandler: 发生异常，关闭通道");
        System.out.println(cause.toString());
        ctx.close();
    }
}
